<template>
  <div class="circleWrapper" ref="melong">
    <!-- 转盘 -->
    <div class="pan">
      <div class="circle">
        <div class="zz">
          <img :src="require('@/assets/img/pointer.svg')" alt="" />
        </div>
        <div
          class="circleSmall"
          id="wheel"
          :style="{ backgroundImage: `url(${require('@/assets/img/circle.png')})` }"
        >
          <!-- 扇形区域 -->
          <div class="sx">
            <canvas id="qCanvas" height="230" width="230" />
          </div>
        </div>
      </div>
    </div>

    <!-- 按键 -->
    <div class="btn">
      <div
        @click="show = true"
        class="xy-button"
        :style="{ backgroundImage: `url(${require('@/assets/img/btn.png')})` }"
      >
        <span>编辑内容</span>
      </div>
    </div>

    <!-- 弹窗 -->
    <van-popup v-model="show">
      <div class="pop-content" :style="{ backgroundImage: `url(${require('@/assets/img/back.png')})` }">
        <div class="card-wrapper" ref="popContent">
          <div class="card-item" v-for="(item, index) in cardItem" :key="item.id">
            <div class="delete" @click="deleteItem(index)">
              <van-icon name="delete"></van-icon>
            </div>
            <div class="item">
              <div class="title">项目😠：</div>
              <div class="value flex1">
                <van-field size="small" placeholder="🍉🍉专属输入框..." v-model="item.value" />
              </div>
            </div>
            <div class="item">
              <div class="title">宽度：</div>
              <div class="value">
                <van-stepper :min="0" :max="100" button-size="18" theme="round" v-model="item.width" />
              </div>
            </div>
          </div>
        </div>
        <!-- 操作 -->
        <div class="tools">
          <van-button
            round
            icon="add"
            style="margin-left: 10px"
            size="small"
            type="info"
            @click="newItem"
          ></van-button>
          <van-button
            round
            style="margin-left: 10px"
            size="small"
            icon="completed"
            type="info"
            @click="saveItem"
          ></van-button>
        </div>
      </div>
    </van-popup>
  </div>
</template>

<script>
export default {
  name: 'CircleRound',
  data() {
    return {
      userId: '',
      show: false,
      preColor: '',
      cardItem: [
        {
          id: this.$xy.RI(),
          value: '跪榴莲',
          loading: false,
          width: ''
        },
        { id: this.$xy.RI(), value: '无条件原谅', loading: false, width: '' },
        { id: this.$xy.RI(), value: '1000字检讨', loading: false, width: '' },
        { id: this.$xy.RI(), value: '打屁股十次', loading: false, width: '' },
        { id: this.$xy.RI(), value: '100个么么', loading: false, width: '' }
      ]
    };
  },
  created() {
    this.init();
  },
  methods: {
    // 初始化
    init() {
      this.$nextTick(() => {
        setTimeout(() => {
          this.getUserInfo();
          this.setCircle();
          this.move();
        });
      });
    },

    getUserInfo() {
      this.userId = this.$xy.SR().userId;

      if (!this.userId) return;

      const user = this.$xy.get('userInfo');

      if (user) {
        if (user.userId === this.userId) {
          this.cardItem = user.cardItem;
        } else {
          this.$xy.set('userInfo', {
            userId: this.userId,
            cardItem: this.cardItem
          });
        }
      } else {
        this.$xy.set('userInfo', {
          userId: this.userId,
          cardItem: this.cardItem
        });
      }
    },

    setCircle() {
      // 获取 canvas 组件的节点
      const canvas = document.querySelector('#qCanvas');

      const ctx = canvas.getContext('2d');

      const width = canvas.width;
      const height = canvas.height;
      const radius = Math.min(width, height) / 2; // 半径
      const centerX = width / 2;
      const centerY = height / 2;
      let startAngle = 0;

      let percent = 100;
      let index = 0;

      this.cardItem.forEach((item) => {
        if (item.width) {
          percent -= parseFloat(item.width);
          index++;
        }
      });

      this.cardItem.forEach((item, __index) => {
        const PI = 2 * Math.PI;

        const angle =
          PI *
          (item.width ? parseFloat(item.width) / 100 : percent / (this.cardItem.length - index) / 100);

        const endAngle = startAngle + angle;

        ctx.beginPath();
        ctx.moveTo(centerX, centerY);
        ctx.strokeStyle = '#666';
        ctx.arc(centerX, centerY, radius, startAngle, endAngle);
        const COLOR = this.randomColor(__index);
        item.color = COLOR;
        ctx.fillStyle = COLOR;
        ctx.fill();
        ctx.stroke();

        ctx.save();
        ctx.fillStyle = '#fff';
        ctx.font = '13px Arial';
        ctx.textBaseline = 'middle';

        ctx.translate(centerX, centerY);
        ctx.rotate((endAngle - startAngle) / 2 + startAngle);
        ctx.fillText(item.value, 35, 0);
        ctx.restore();

        startAngle = endAngle;
      });
    },

    // 删除
    deleteItem(index) {
      this.cardItem.splice(index, 1);
    },

    // 添加一项
    newItem() {
      this.cardItem.push({
        id: this.$xy.RI(),
        value: '',
        width: '',
        loading: false
      });

      this.$nextTick(() => {
        setTimeout(() => {
          /* 滚动到容器最底部 */
          this.$refs.popContent.scrollTop = this.$refs.popContent.scrollHeight;
        });
      });
    },

    // 保存一项
    saveItem() {
      this.show = false;
      this.setCircle();
      this.$xy.set('userInfo', {
        userId: this.userId,
        cardItem: this.cardItem
      });
    },

    // 产生随机的颜色数值
    randomColor(index = -5) {
      const colors = ['#72cdec', '#df6937', '#f5f451', '#a1d45c', '#418cad', '#7c9fce', '#f095a9'];

      const C = colors[Math.floor(Math.random() * 7)];

      if (index === this.cardItem.length - 1 && this.cardItem.length > 2) {
        /* 最后一个 */
        if (this.cardItem[0].color === C) {
          return this.randomColor();
        } else if (C !== this.preColor) {
          this.preColor = C;
          return C;
        } else {
          return this.randomColor();
        }
      } else if (C !== this.preColor) {
        this.preColor = C;
        return C;
      } else {
        return this.randomColor();
      }
    },

    // 转盘转动
    move() {
      const wheel = document.getElementById('wheel');
      let isDragging = false;
      let startAngle = 0;
      let currentAngle = 0;
      let rotationSpeed = 0; // 旋转速度
      let startTime = 0; // 开始滑动的时间
      let endTime = 0; // 结束滑动的时间
      let startDistance = []; // 开始滑动的距离
      let endDistance = []; // 结束滑动的距离
      let inertiaInterval; // 惯性旋转的计时器

      wheel.addEventListener('touchstart', handleTouchStart);
      wheel.addEventListener('touchmove', handleTouchMove);
      wheel.addEventListener('touchend', handleTouchEnd);

      function handleTouchStart(event) {
        isDragging = true;
        startAngle = getAngle(event.touches[0].clientX, event.touches[0].clientY);
        startDistance = [event.touches[0].clientX, event.touches[0].clientY];
        clearInterval(inertiaInterval);

        startTime = new Date().getTime();
      }

      function handleTouchMove(event) {
        if (!isDragging) return;

        event.preventDefault();

        const touchX = event.touches[0].clientX;
        const touchY = event.touches[0].clientY;

        const angle = getAngle(touchX, touchY);

        const deltaAngle = -(angle - startAngle); // 取反，使旋转方向与滑动方向一致

        currentAngle += deltaAngle;
        startAngle = angle;

        wheel.style.transform = `rotate(${currentAngle}deg)`;
      }

      function handleTouchEnd(event) {
        isDragging = false;
        endTime = new Date().getTime();
        endDistance = [event.changedTouches[0].clientX, event.changedTouches[0].clientY];

        const duration = endTime - startTime; // 滑动的时间间隔
        let distance;

        distance = Math.sqrt(
          Math.pow(startDistance[0] - endDistance[0], 2) + Math.pow(startDistance[1] - endDistance[1], 2)
        );

        const Xs = startDistance[0];
        const Ys = startDistance[1];
        const Xe = endDistance[0];
        const Ye = endDistance[1];

        const ABX = Xs - 187;
        const ABY = Ys - 300;
        const ACX = Xe - 187;
        const ACY = Ye - 300;

        var direct = ABX * ACY - ABY * ACX; // AB与AC叉乘求出逆时针还是顺时针旋转

        if (direct > 0) {
          // 根据滑动距离和时间计算旋转速度，并调整基数使得转速更快
          rotationSpeed = (distance / duration) * 30;
        } else {
          // 根据滑动距离和时间计算旋转速度，并调整基数使得转速更快
          rotationSpeed = (-distance / duration) * 30;
        }

        inertiaInterval = setInterval(inertiaRotate, 16);
      }

      function inertiaRotate() {
        if (!isDragging && Math.abs(rotationSpeed) > 0.1) {
          currentAngle += rotationSpeed;

          rotationSpeed *= 0.98; // 逐渐减小旋转速度

          wheel.style.transform = `rotate(${currentAngle}deg)`;
        } else {
          clearInterval(inertiaInterval);
        }
      }

      function getAngle(x, y) {
        const rect = wheel.getBoundingClientRect();
        const centerX = rect.left + rect.width / 2;
        const centerY = rect.top + rect.height / 2;

        const deltaX = x - centerX;
        const deltaY = centerY - y; // Y轴方向与数学坐标系相反

        let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
        if (angle < 0) {
          angle += 360;
        }

        return angle;
      }
    }
  }
};
</script>

<style lang="scss">
.circleWrapper {
  font-size: 13px;
  padding-top: 100px;
  height: 100vh;
  box-sizing: border-box;
  margin: 0;
  overflow: hidden;
  --bg-imgurl: url(~@/assets/img/gua.jpg);

  &::after {
    z-index: -1;
    position: absolute;
    height: 100%;
    width: 100%;
    display: block;
    content: '';
    top: 0;
    left: 0;
    background-image: var(--bg-imgurl);
    background-repeat: no-repeat;
    background-position: 50% 50%;
    background-size: cover;
    filter: blur(2px);
  }

  @keyframes bounce-in-top {
    0% {
      -webkit-transform: translateY(-500px);
      transform: translateY(-500px);
      -webkit-animation-timing-function: ease-in;
      animation-timing-function: ease-in;
      opacity: 0;
    }

    38% {
      -webkit-transform: translateY(0);
      transform: translateY(0);
      -webkit-animation-timing-function: ease-out;
      animation-timing-function: ease-out;
      opacity: 1;
    }

    55% {
      -webkit-transform: translateY(-65px);
      transform: translateY(-65px);
      -webkit-animation-timing-function: ease-in;
      animation-timing-function: ease-in;
    }

    72% {
      -webkit-transform: translateY(0);
      transform: translateY(0);
      -webkit-animation-timing-function: ease-out;
      animation-timing-function: ease-out;
    }

    81% {
      -webkit-transform: translateY(-28px);
      transform: translateY(-28px);
      -webkit-animation-timing-function: ease-in;
      animation-timing-function: ease-in;
    }

    90% {
      -webkit-transform: translateY(0);
      transform: translateY(0);
      -webkit-animation-timing-function: ease-out;
      animation-timing-function: ease-out;
    }

    95% {
      -webkit-transform: translateY(-8px);
      transform: translateY(-8px);
      -webkit-animation-timing-function: ease-in;
      animation-timing-function: ease-in;
    }

    100% {
      -webkit-transform: translateY(0);
      transform: translateY(0);
      -webkit-animation-timing-function: ease-out;
      animation-timing-function: ease-out;
    }
  }

  .pan {
    height: 400px;
    display: flex;
    justify-content: center;
    align-items: center;
    animation: bounce-in-top 1.5s both;
    position: relative;
    box-sizing: border-box;
  }

  .circle {
    background-color: #ffb3b3;
    height: 265px;
    width: 265px;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    box-shadow: 0 0 10px #ff8f8f;
    box-sizing: border-box;
  }

  .circleSmall {
    box-sizing: border-box;
    background-color: #ffb3b3;
    padding: 11px;
    height: 265px;
    width: 265px;
    border-radius: 50%;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    box-sizing: border-box;
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center center;
  }

  .btn {
    position: fixed;
    width: 100%;
    bottom: 0;
    justify-content: center;
    display: flex;
    padding: 20px 30px 50px 30px;
    box-sizing: border-box;

    .xy-button {
      width: 160px;
      height: 50px;
      @include xy-dfc;
      background-repeat: no-repeat;
      background-size: contain;
      background-position: center center;
      color: #fff;
      font-size: 13px;
      font-family: 'heiti';
      font-weight: bold;

      &:active {
        opacity: 0.8;
      }
    }
  }

  .zz {
    position: absolute;
    width: 20px;
    height: 20px;
    font-size: 21px;
    background-color: #ffb7b7;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    box-shadow: 0 2px 0px rgba(139, 139, 139, 0.5);
    z-index: 99;

    img {
      position: absolute;
      bottom: 0;
    }
  }

  .sx {
    height: calc(100% - 20px);
    width: calc(100% - 20px);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    position: relative;
    overflow: hidden;
    border-radius: 50%;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5) inset;
  }

  .sx-item {
    position: absolute;
    top: 0;
    height: 50%;
    width: 50%;
    left: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    transform-origin: left bottom;
  }

  #qCanvas {
    height: 100%;
    width: 100%;
  }

  .van-popup {
    overflow: hidden;
    border-radius: 5px;
  }

  .pop-content {
    width: 90vw;
    padding: 36px 30px 46px 30px;
    box-sizing: border-box;
    background-repeat: no-repeat;
    background-size: 100% 100%;

    .van-button {
      padding: 5px 15px;
    }
  }

  .card-item {
    padding: 15px 10px;
    background-color: #eeeeee;
    margin-bottom: 20px;
    position: relative;
    border-radius: 5px;
    box-shadow: $--xy-shadow;

    .delete {
      position: absolute;
      bottom: 12px;
      right: 10px;
      background-color: #fff;
      border: 1px solid #eee;
      padding: 5px;
      border-radius: 10px;

      &:active {
        background-color: #fffafa;
        color: #f00;
      }
    }

    .item {
      display: flex;
      align-items: center;
      margin-bottom: 15px;

      .van-cell {
        border-radius: 5px;
      }

      .title {
        margin-right: 10px;
        width: 60px;
        color: #666;
      }

      &:last-child {
        margin-bottom: 0;
      }
    }
  }

  .card-wrapper {
    max-height: 65vh;
    overflow-y: auto;
    opacity: 0.85;
    @include xy-scroll;
  }

  .tools {
    position: absolute;
    right: 10px;
    bottom: 10px;
    padding-top: 10px;
    display: flex;
    justify-content: flex-end;

    .van-button {
      padding: 0;
      height: 32px;
      width: 32px;
    }

    .van-icon {
      font-size: 16px;
    }
  }

  .custom-button {
    width: 26px;
    color: #fff;
    font-size: 10px;
    line-height: 18px;
    text-align: center;
    background-color: #1989fa;
    border-radius: 100px;
  }

  .van-field {
    padding: 5px 10px;
  }

  canvas {
    text-rendering: optimizeLegibility;
  }
}
</style>
